package com.sssre.business.service.impl;

import com.sssre.business.domain.TestDriveInfo;
import com.sssre.business.exception.ServiceValidException;
import com.sssre.business.mapper.TestDriveInfoMapper;
import com.sssre.business.service.ITestDriveInfoService;
import com.sssre.business.util.DateUtil;
import com.sssre.business.util.EffectiveTimeUtil;
import com.sssre.business.util.RegexUtils;
import com.sssre.business.util.VehiclePlateNoUtil;
import com.sssre.common.utils.StringUtils;
import com.sssre.system.domain.SysConfig;
import com.sssre.system.mapper.SysConfigMapper;
import com.sssre.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 浪兎兎
 * @create 2025-05-14-8:59
 */
@Service
public class TestDriveInfoServiceImpl implements ITestDriveInfoService {
    @Autowired
    private TestDriveInfoMapper testDriveInfoMapper;
    @Autowired
    private ISysConfigService sysConfigService;

    /**
     * 查询试驾预约列表
     *
     * @param testDriveInfo 参数
     * @return 结果
     */
    @Override
    public List<TestDriveInfo> selectList(TestDriveInfo testDriveInfo) {
        return testDriveInfoMapper.selectList(testDriveInfo);
    }

    /**
     * 新增
     *
     * @param testDriveInfo 新增的预约单
     * @return 结果
     */
    @Override
    public int add(TestDriveInfo testDriveInfo) {
        // 校验参数合法性
        if (testDriveInfo == null) {
            throw new ServiceValidException("参数非法");
        }
        String customerName = testDriveInfo.getCustomerName();
        Integer appointmentModel = testDriveInfo.getAppointmentModel();
        if (StringUtils.isEmpty(customerName) || appointmentModel == null) {
            throw new ServiceValidException("参数非法");
        }
        Date appointmentDate = testDriveInfo.getAppointmentDate();
        if (appointmentDate == null) {
            throw new ServiceValidException("参数非法");
        }
        // 校验联系方式的合法性
        String customerContact = testDriveInfo.getCustomerContact();
        if (StringUtils.isEmpty(customerContact) || !RegexUtils.isPhoneLegal(customerContact)) {
            throw new ServiceValidException("手机号格式错误");
        }
        // 校验预约时间的合法性：格式必须为"HH:mm"，且必须为半点或者整点
        Date appointmentTime = testDriveInfo.getAppointmentTime();
        if (appointmentTime == null) {
            throw new ServiceValidException("参数非法");
        }
        try {
            boolean point = DateUtil.isHalfPointOrWholePoint(appointmentTime);
            if (!point) throw new ServiceValidException("");
        } catch (RuntimeException e) {
            throw new ServiceValidException("时间格式错误");
        }
        // 每一时间不能有相同的预约单
        TestDriveInfo sameTime = testDriveInfoMapper.selectByAppointmentTime(DateUtil.toDateString("HH:mm", appointmentTime), appointmentDate);
        if (sameTime != null) {
            throw new ServiceValidException("每一时间不能有其他的预约单");
        }
        // 校验预约日期的合法性：必须在当前时间之后，且每一天不能有相同联系方式的预约单

        if (!DateUtil.montage(appointmentDate, appointmentTime).after(new Date())) {
            throw new ServiceValidException("预约时间必须在当前时间之后");
        }
        // 联系方式+预约时间需要唯一
        TestDriveInfo same = testDriveInfoMapper.selectByAppointmentDateAndContact(customerContact, appointmentDate);
        if (same != null) {
            throw new ServiceValidException("每一天不能有相同联系方式的预约单");
        }
        // 设置创建时间
        testDriveInfo.setCreatedAt(new Date());
        // 新增数据
        return testDriveInfoMapper.add(testDriveInfo);
    }

    /**
     * 修改
     *
     * @param testDriveInfo 修改的预约单
     * @return 结果
     */
    @Override
    public int edit(TestDriveInfo testDriveInfo) {
        // 校验参数合法性
        if (testDriveInfo == null) {
            throw new ServiceValidException("参数非法");
        }
        Integer id = testDriveInfo.getID();
        String customerName = testDriveInfo.getCustomerName();
        Integer appointmentModel = testDriveInfo.getAppointmentModel();
        if (id == null || StringUtils.isEmpty(customerName) || appointmentModel == null) {
            throw new ServiceValidException("参数非法");
        }
        Date appointmentDate = testDriveInfo.getAppointmentDate();
        if (appointmentDate == null) {
            throw new ServiceValidException("参数非法");
        }
        // 数据被删除过就不能修改
        TestDriveInfo oldTestDriveInfo = testDriveInfoMapper.selectOneById(testDriveInfo.getID().longValue());
        if (oldTestDriveInfo.isDelete()) {
            throw new ServiceValidException("非法参数");
        }
        // 校验联系方式的合法性
        String customerContact = testDriveInfo.getCustomerContact();
        if (StringUtils.isEmpty(customerContact) || !RegexUtils.isPhoneLegal(customerContact)) {
            throw new ServiceValidException("手机号格式错误");
        }
        // 校验预约时间的合法性：格式必须为"HH:mm"，且必须为半点或者整点
        Date appointmentTime = testDriveInfo.getAppointmentTime();
        if (appointmentTime == null) {
            throw new ServiceValidException("参数非法");
        }
        try {
            boolean point = DateUtil.isHalfPointOrWholePoint(appointmentTime);
            if (!point) throw new ServiceValidException("");
        } catch (RuntimeException e) {
            throw new ServiceValidException("时间格式错误");
        }
        // 每一时间不能有相同的预约单
        TestDriveInfo sameTime = testDriveInfoMapper.selectByAppointmentTime(DateUtil.toDateString("HH:mm", appointmentTime), appointmentDate);
        if (sameTime != null) {
            if (!sameTime.getID().equals(testDriveInfo.getID())) {
                throw new ServiceValidException("每一时间不能有其他的预约单");
            }
        }
        // 校验预约时间的合法性：必须在当前时间之后，且每一天不能有相同联系方式的预约单
        if (!DateUtil.montage(appointmentDate, appointmentTime).after(new Date())) {
            throw new ServiceValidException("预约时间必须在当前时间之后");
        }
        // 联系方式+预约时间需要唯一
        TestDriveInfo same = testDriveInfoMapper.selectByAppointmentDateAndContact(customerContact, appointmentDate);
        if (same != null) {
            if (!same.getID().equals(testDriveInfo.getID())) {
                throw new ServiceValidException("每一天不能有相同联系方式的预约单");
            }
        }
        // 已经试驾过的不能修改
        if (StringUtils.isNotEmpty(oldTestDriveInfo.getLicensePlate()) || oldTestDriveInfo.getActualStartTime() != null || oldTestDriveInfo.getActualEndTime() != null || StringUtils.isNotEmpty(oldTestDriveInfo.getCustomerFeedback()) || oldTestDriveInfo.getCustomerRating() != null) {
            throw new ServiceValidException("已经试驾过的不能修改");
        }
        // 修改数据
        return testDriveInfoMapper.edit(testDriveInfo);
    }

    /**
     * 查询一个
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    public TestDriveInfo selectOneById(Long id) {
        // 校验数据合法性
        if (id == null) {
            throw new ServiceValidException("非法参数");
        }
        return testDriveInfoMapper.selectOneById(id);
    }

    /**
     * 删除
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    public int delete(Long id) {
        // 校验数据合法性
        if (id == null) {
            throw new ServiceValidException("非法参数");
        }
        // 数据被删除过就不能删除
        TestDriveInfo testDriveInfo = testDriveInfoMapper.selectOneById(id);
        if (testDriveInfo.isDelete()) {
            throw new ServiceValidException("非法参数");
        }
        // 已经试驾过的不能删除
        if (StringUtils.isNotEmpty(testDriveInfo.getLicensePlate()) || testDriveInfo.getActualStartTime() != null || testDriveInfo.getActualEndTime() != null || StringUtils.isNotEmpty(testDriveInfo.getCustomerFeedback()) || testDriveInfo.getCustomerRating() != null) {
            throw new ServiceValidException("已经试驾过的不能删除");
        }
        // 进行软删除
        return testDriveInfoMapper.deleteById(id);
    }

    /**
     * 反馈
     *
     * @param testDriveInfo 反馈的预约单
     * @return 结果
     */
    @Override
    public int feedback(TestDriveInfo testDriveInfo) {
        // 校验数据合法性
        if (testDriveInfo == null) {
            throw new ServiceValidException("非法参数");
        }
        // 查询原始对象
        Integer id = testDriveInfo.getID();
        TestDriveInfo oldTestDriveInfo = testDriveInfoMapper.selectOneById(id.longValue());
        if (oldTestDriveInfo == null) {
            throw new ServiceValidException("非法参数");
        }
        Date actualStartTime = testDriveInfo.getActualStartTime();
        Date actualEndTime = testDriveInfo.getActualEndTime();
        if ((actualStartTime == null || actualEndTime == null)) {
            throw new ServiceValidException("非法参数");
        }
        // 数据被删除过就不能修
        if (oldTestDriveInfo.isDelete()) {
            throw new ServiceValidException("非法参数");
        }
        // 校验分数的合法性
        Integer customerRating = testDriveInfo.getCustomerRating();
        if (customerRating == null || customerRating < 0 || customerRating > 10) {
            throw new ServiceValidException("非法参数");
        }
        // 已经试驾过的不能修改
        if (StringUtils.isNotEmpty(oldTestDriveInfo.getLicensePlate()) || oldTestDriveInfo.getActualStartTime() != null || oldTestDriveInfo.getActualEndTime() != null || StringUtils.isNotEmpty(oldTestDriveInfo.getCustomerFeedback()) || oldTestDriveInfo.getCustomerRating() != null) {
            throw new ServiceValidException("已经试驾过的不能修改");
        }
        // 校验车牌号的合法性
        String licensePlate = testDriveInfo.getLicensePlate();
        if (StringUtils.isEmpty(licensePlate) || VehiclePlateNoUtil.getVehiclePlateNo(licensePlate) == null) {
            throw new ServiceValidException("车牌号格式错误");
        }
        // 校验开始时间和结束时间的合法性:开始时间与结束时间不相差半个小时
        long time = actualEndTime.getTime() - actualStartTime.getTime();
        if (time <= 0) {
            throw new ServiceValidException("开始时间不能早于结束时间");
        } else if (time > DateUtil.HALF_HOUR) {
            throw new ServiceValidException("开始时间与结束时间不能相差半小时");
        }
//        Date minus = DateUtil.minus(actualEndTime, actualStartTime);
//        int minute = DateUtil.getMinute(minus);
//        if (minute > 30) {
//            throw new ServiceValidException("开始时间与结束时间最多相差半小时");
//        }
        // 开始时间似乎不能早于预约时间？
        if (oldTestDriveInfo.getAppointmentDate().after(actualStartTime)) {
            throw new ServiceValidException("开始时间不能早于预约时间");
        }
        // 修改
        return testDriveInfoMapper.feedback(testDriveInfo);
    }

    /**
     * 返回有效的预约日期范围
     * @param id 主键
     * @param appointmentDate 预约日期
     * @return 结果
     */
    @Override
    public List<String> effectiveTime(Integer id, Date appointmentDate) {
        // 参数合法性校验
        if (appointmentDate == null) {
            throw new ServiceValidException("非法参数");
        }
        // 查询可用时间列表
        List<Date> dates = testDriveInfoMapper.selectEffectiveTime(id, appointmentDate);
        List<String> collect = dates.stream().map(date -> DateUtil.toDateString("HH:mm", date)).collect(Collectors.toList());
        // 获取开始时间和结束时间
        String startTime = sysConfigService.selectConfigByKey("startTime");
        String endTime = sysConfigService.selectConfigByKey("endTime");
        // 转换时间范围
        return EffectiveTimeUtil.getAvailableTimeSlots(startTime, endTime, collect);
    }
}
